using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using OOAD_Project_Engine.Application.Services;
using OOAD_Project_Editor.Domain;
using OOAD_Project_Editor.Foundation;
using OOAD_Project_Engine.Foundation;
using OOAD_Project_Engine.Domain.Entities;
using OOAD_Project_Engine.Foundation.Interfaces;
using OOAD_Project_Editor.Domain.ManageSceneActions;
using OOAD_Project_Editor.Foundation.Script;

namespace OOAD_Project_Editor.Application
{
    public class ManageSceneHandler : GameComponent, IManageSceneHandler
    {
        public IEditableSceneComponent CurrentScene { get { return _currentScene; } }
        EditableSceneComponent _currentScene;
        ContentProvider contentProvider;
        GraphicService graphicService;
        public IActionHandler ActionHandler { get; protected set; }
        public event EventHandler<SceneUpdateEventArgs> OnFormUpdate;

        public ManageSceneHandler(Game game)
            : base(game)
        {
            GameHelper.Game = game;
            contentProvider = new ContentProvider(game);
            game.Components.Add(contentProvider);
            graphicService = new GraphicService(game);
            Game.Components.Add(graphicService);
            ActionHandler = new ActionHandler(game);
            Game.Components.Add(ActionHandler);
        }

        private void onSceneUpdate(object sender, EventArgs e)
        {
            if (OnFormUpdate != null)
                OnFormUpdate(this, new SceneUpdateEventArgs(_currentScene));
        }

        public void CreateEmptyScene()
        {
            removeOldScene();
            _currentScene = new EditableSceneComponent(Game);
            IniitializeScene(_currentScene);
            onSceneUpdated();
        }

        public void SetManageScene(SceneScript script)
        {
            if (script != null)
            {
                removeOldScene();
                _currentScene = new EditableSceneComponent(Game, script);
                IniitializeScene(_currentScene);
                onSceneUpdated();
            }
        }

        private void removeOldScene()
        {
            if (_currentScene != null && Game.Components.Contains(_currentScene))
                Game.Components.Remove(_currentScene);
         
        }

        private void IniitializeScene(EditableSceneComponent scene)
        {
            scene.DrawOrder = 10;
            Game.Components.Add(scene);
            scene.Initialize();
            ActionHandler.Initialize();
            scene.OnUpdateFinished += onSceneUpdate;
        }

        #region Actions

        private void SelectEntityByMouse()
        {
            MouseState state = Mouse.GetState();
            IEntity result = _currentScene.TryGetByTransform(state.X, state.Y);
            onSelectEntity(result);
        }

        public void SelectEntityByName(string name)
        {
            IEntity result = _currentScene.TryGetByName(name);
            onSelectEntity(result);
        }

        public void CutEntity()
        {
            if (ActionHandler.AddAction(EActionType.CutEntity, _currentScene, ActionHandler.SelectEntity) != null)
            {
                ActionHandler.SelectEntity = null;
                onSceneUpdated();
            }

        }

        public void CopyEntity()
        {
            if (ActionHandler.AddAction(EActionType.CopyEntity, _currentScene, ActionHandler.SelectEntity) != null)
                onSceneUpdated();
        }

        public void PasteEntity()
        {
            if (ActionHandler.AddAction(EActionType.PasteEntity, _currentScene) != null)
                onSceneUpdated();
        }

        public void DuplicateEntity(string name, IEntity entityPrototype)
        {
            if (ActionHandler.AddAction(EActionType.DuplicateEntity, _currentScene, name, entityPrototype) != null)
                onSceneUpdated();
        }

        public void AddEntityComponent(IEntity entity, Type componentType, params object[] param)
        {
            if (ActionHandler.AddAction(EActionType.AddEntityComponent, _currentScene, entity, componentType, param) != null)
                onSceneUpdated();
        }

        public void RemoveEntity(IEntity entity)
        {
            if (ActionHandler.AddAction(EActionType.RemoveEntity, _currentScene, entity) != null)
                onSceneUpdated();
        }

        public void RemoveEntityComponent(IEntity entity, IEntityComponent component)
        {
            if (ActionHandler.AddAction(EActionType.RemoveEntityComponent, _currentScene, entity, component) != null)
                onSceneUpdated();
        }

        private void onSelectEntity(IEntity result)
        {
            ActionHandler.SelectEntity = result;
            onSceneUpdated();
        }

        public void OnMouseDown()
        {
            SelectEntityByMouse();
            ActionHandler.EntityDragStart();
            onSceneUpdated();
        }

        public void OnMouseMove()
        {
            ActionHandler.EntityDraging();
        }

        public void OnMouseUp()
        {
            ActionHandler.EntityDragEnd();
            onSceneUpdated();
        }

        #endregion

        private void onSceneUpdated()
        {
            _currentScene.OnUpdateFinished += onSceneUpdate;
        }

    }
}
